﻿(function ($) {
    $.fn.MultiSiteDynamicTreeEditor = function (settings) {
        var res = this; //jquery object//context
        res.settings = settings;
        res.ui = res.find(".dtp_content");
        res.panel = res.find(".dtp_panel");
        res.results = res.find(".results");
        res.Add = function (node) { return Add(node, res); };
        res.Change = function (node) { return Change(node, res); };
        res.Up = function (node) { return Up(node, res); };
        res.Down = function (node) { return Down(node, res); };
        res.Delete = function (node) { return Delete(node, res); };
        res.Edit = function (node) { return Edit(node, res); };
        res.Refresh = function () { return Refresh(res); };
        res.UpdateResult = function () { return UpdateResult(res); };
        res.Refresh();
        res.UpdateResult();
        return res;
    };

    function Refresh(o) {//refresh nodes data depends of ul-li list
        o.nodes = [];
        RenderAddButtons(o);
        o.ui.find("li").each(function (p, li) {
            ParceNode($(li), o);
        });
    };
    function UpdateResult(o) {
        o.results.val('[]');
        var result = "{\"Nodes\":[";
        var nodes = [];
        var liItems = o.ui.find("li");
        if (o.settings.MaxAmountItems > 0 && liItems.length >= o.settings.MaxAmountItems) {
            o.panel.hide();
        } else {
            o.panel.show();
        };
        liItems.each(function (p, li) {
            var ndata = NodeToData($(li), o);
            var exists = false;
            $(nodes).each(function (px, node) {
                exists = (ndata.data == node.data && ndata.type == node.type);
                if (exists) return false;
            });
            if (!exists && ndata.data && ndata.type) {
                nodes.push(ndata);
                if (result.length > 10) result = result + ",";
                result = result + "{\"id\":\"" + String(ndata.data).replace("\"", "\\\"") + "\",\"data\":\"" + String(ndata.data).replace("\"", "\\\"") + "\",\"type\":\"" + String(ndata.type).replace("\"", "\\\"") + "\"}";
            };
        });
        result = result + "]}";
        o.results.val(result);
    };
    function Add(node, o) {
        var exists = false;
        $(o.nodes).each(function (p, ndata) {
            exists = (ndata.data == node.data && ndata.type == node.type);
            if (exists) return false;
        });
        if (exists) UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('error', 'node already exist!', "Same node exist in the list! [" + String(node.data) + "," + String(node.type) + "]Can't save result. Please choose other node!");
        else {
            var linode = DataToNode(node, o);
            linode.appendTo(o.ui);
            ParceNode(linode, o);
        };
        o.UpdateResult();
    }
    function Change(node, o) {
        var linode = FindLi(node, o);
        $(o.settings.Types).each(function (p, picker) {
            if (node.type == picker.TreeAlias) {
                picker.data = node.data;
                picker.path = node.info ? node.info.path : node.data;
                ShowNodePicker(picker, function (result) {
                    var nnode = { type: result.TreeAlias, data: result.data };
                    var exists = false;
                    $(o.nodes).each(function (p1, ndata) {
                        exists = (ndata.data == nnode.data && ndata.type == nnode.type);
                        if (exists) return false;
                    });
                    if (exists) UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('error', 'node already exist!', "Same node exist in the list! [" + String(node.data) + "," + String(node.type) + "]Can't process changes. Please choose other node!");
                    else {
                        linode.addClass("processing");
                        var newLiNode = DataToNode(nnode, o);
                        newLiNode.insertBefore(linode);
                        Delete(node, o);
                        o.nodes.push(nnode);
                        ShowNodeInfo(newLiNode, nnode, o);
                    };
                });
                return false;
            };
        });
        o.UpdateResult();
    }
    function Up(node, o) {
        var linode = FindLi(node, o);
        var prev = linode.prev();
        if (prev.length > 0) {
            linode.addClass("processing");
            linode.fadeOut('fast', function () {
                linode.insertBefore(prev);
                linode.fadeIn('fast', function () {
                    linode.removeClass("processing"); o.UpdateResult();
                });
            });
        };
    }
    function Down(node, o) {
        var linode = FindLi(node, o);
        var next = linode.next();
        if (next.length > 0) {
            linode.addClass("processing");
            linode.fadeOut('fast', function () {
                linode.insertAfter(next);
                linode.fadeIn('fast', function () {
                    linode.removeClass("processing"); o.UpdateResult();
                });
            });
        };
    }
    function Delete(node, o) {
        var linode = FindLi(node, o);
        linode.remove();
        var l = o.nodes.length;
        var tanode = o.nodes.shift();
        while (l > 0 && tanode != node) {
            o.nodes.push(tanode);
            tanode = o.nodes.shift();
        };
        o.UpdateResult();
    }
    function Edit(node, o) {
        var linode = FindLi(node, o);
        $(o.settings.Types).each(function (p, picker) {
            if (node.type == picker.TreeAlias) {
                picker.data = node.data;
                picker.path = node.info ? node.info.path : node.data;
                var resUrl = TransformTemplate(picker.editurl + '&rnd=' + uuidFast(), picker, false);
                UmbClientMgr.openModalWindow(resUrl, "Edit -" + picker.TreeAlias + "- node:", true, picker.editwidth, picker.editheight, 0, 0, false, function (mdlwnd) {
                    picker.data = mdlwnd.outVal;
                    UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('warning', 'Refresh this page...', 'New information will be visible only after reloading page!');
                });
                return false;
            };
        });
    }
    function FindLi(node, o) {
        var res = null;
        o.ui.find("li").each(function (p, li) {
            var ndata = NodeToData($(li), o);
            if (ndata.type == node.type && ndata.data == node.data) res = $(li);
            if (res) return false;
        });
        return res;
    }
    function ParceNode(linode, o) {
        var ndata = NodeToData(linode, o);
        if (!ndata.type || !ndata.data) {
            var btdel = $("<span class='chgdel'><img class='bdel' src='/umbraco/ism/fields/dynamictreepicker/images/b_delete.png' alt='delete this from list...'/></span>");
            btdel.click(function () { linode.remove(); });
            btdel.appendTo(linode);
            linode.addClass("error");
        } else {
            o.nodes.push(ndata);
            linode.addClass("processing");
            var newLiNode = DataToNode(ndata, o);
            newLiNode.insertBefore(linode);
            linode.remove();
            ShowNodeInfo(newLiNode, ndata, o);
        };
        o.UpdateResult();
    }

    function ShowNodeInfo(el, ndata, o) {
        el.attr("title", String(ndata.data) + " [" + String(ndata.type) + "]");
        $.ajax({
            url: '/umbraco/webservices/TreeNodeData.ashx?rndo=' + uuidFast() + '',
            dataType: 'json',
            data: ndata,
            success: function (d, s, j) {
                ndata.info = d;
                ShowUpDown(el, ndata, o);
                ShowEditDelete(el, ndata, o);
                GetNodePath(ndata, function (node) {
                    node.Path = "";
                    $(node.info.parents).each(function (p, pitem) {
                        if (pitem["info"]) node.Path = node.Path + "/" + pitem["info"].name;
                    });
                    el.ntitle.html('');
                    el.npath = $("<span class='npath' style=''>" + node.Path + "</span>");
                    el.npath.appendTo(el.ntitle);
                    if (node.info.icon) {
                        if (node.info.icon[0] == ".") el.npath.addClass(node.info.icon.substring(1, node.info.icon.length));
                        else el.npath.css("background-image", "url(/umbraco/images/umbraco/" + node.info.icon);
                    };
                    el.pos.text(Number(el.index()) + 1);
                    el.npath.hover(function () {
                        el.pos.text(Number(el.index()) + 1);
                        el.pos.addClass("highlighten");
                    }, function () {
                        el.pos.removeClass("highlighten");
                    });
                    el.npath.click(function () { o.Change(ndata); });
                    el.attr("title", "[" + String(ndata.data) + "] " + node.Path + " (" + String(ndata.type) + ")");
                });
            },
            error: function () {
                el.addClass("error");
                ShowUpDown(el, ndata, o);
                ShowEditDelete(el, ndata, o);
                el.bchage.hide();
            }
        });
    }


    function NodeToData(linode, o) {
        var r = {
            type: linode.find(".ntype").val(),
            data: linode.find(".nval").val()
        };
        return r;
    };
    function DataToNode(data, o) {
        var linode = $("<li><span class='npos'><!--a--></span><input type=\"hidden\" class=\"ntype\" value=\"\" /><input type=\"hidden\" class=\"nval\" value=\"\" /><span class='updwn'><!----></span><span class=\"ntitle\"><!--t--></span><span class='chgdel'><!--cd--></span></li>");
        linode.ntype = linode.find(".ntype"); linode.ntype.val(data.type);
        linode.nval = linode.find(".nval"); linode.nval.val(data.data);
        linode.ntitle = linode.find(".ntitle"); linode.ntitle.html(data.data);
        linode.nbupdown = linode.find(".updwn");
        linode.nbdelchg = linode.find(".chgdel");
        linode.pos = linode.find(".npos");
        return linode;
    };

    function RenderAddButtons(o) {
        o.panel.buttons = [];
        $(o.settings.Types).each(function (p, picker) {
            picker = $.extend(true, picker, defaultPicker, picker);
            $(picker.Settings).each(function (p1, sitem) {//ovverride from settings
                picker[sitem.Key] = sitem.Value;
            });
            var bnode = $("<li><input type=\"hidden\" class=\"btype\" value=\"\" /><input type=\"hidden\" class=\"bval\" value=\"\" /><span class=\"btitle\"><!--t--></span></li>");
            bnode.appendTo(o.panel);
            bnode.find(".btype").val(picker.TreeAlias);
            bnode.find(".bval").val(picker.StartFrom);
            bnode.find(".btitle").html("<img src='/umbraco/ism/fields/dynamictreepicker/images/tree/add_" + picker.TreeAlias + ".png' alt='treeimg'/>");
            bnode.attr("title", "+add " + picker.TreeAlias + " from:" + String(picker.StartFrom));

            bnode.click(function () {
                ShowNodePicker(picker, function (result) {
                    var rnode = { type: result.TreeAlias, data: result.data };
                    o.Add(rnode);
                }, o);
            });

            o.panel.buttons.push(bnode);
        });
    };

    function ShowUpDown(linode, ndata, o) {
        linode.nbupdown.html("<img class='bup' src='/umbraco/ism/fields/dynamictreepicker/images/b_up.png'/><img class='bdown' src='/umbraco/ism/fields/dynamictreepicker/images/b_down.png'/>");
        linode.bup = linode.nbupdown.find(".bup");
        linode.bup.click(function () { o.Up(ndata); });
        linode.bdown = linode.nbupdown.find(".bdown");
        linode.bdown.click(function () { o.Down(ndata); });
    }

    function ShowEditDelete(linode, ndata, o) {
        linode.nbdelchg.html("<img class='bchng' src='/umbraco/ism/fields/dynamictreepicker/images/b_change.png' tilte='click to choose other one...' alt='chage " + ndata.type + "...'/><img class='bdel' src='/umbraco/ism/fields/dynamictreepicker/images/b_delete.png' alt='delete this from list...'/><img class='bedit' src='/umbraco/ism/fields/dynamictreepicker/images/b_edit.png' alt='edit'/>");
        linode.bchage = linode.nbdelchg.find(".bchng");
        linode.bchage.click(function () { o.Change(ndata); });
        linode.bdel = linode.nbdelchg.find(".bdel");
        linode.bdel.click(function () { o.Delete(ndata); });
        linode.bedt = linode.nbdelchg.find(".bedit");
        linode.bedt.click(function () { o.Edit(ndata); });
    }

    function GetNodePath(node, callBack) {
        var path = node.info.name;
        var l = node.info.parents ? node.info.parents.length : 0;
        $(node.info.parents).each(function (p, pitem) {
            $.ajax({
                url: '/umbraco/webservices/TreeNodeData.ashx?rndo=' + uuidFast() + '',
                dataType: 'json',
                data: { type: node.type, data: pitem },
                success: function (d, s, j) {
                    node.info.parents[p] = { info: d };
                    l--;
                    if (l <= 0) callBack(node);
                },
                error: function () {
                    l--;
                    if (l <= 0) callBack(node);
                }
            });
        });
    }

    function ShowNodePicker(picker, onresult, o) {
        var resUrl = TransformTemplate(picker.url + '&rnd=' + uuidFast(), picker, false);
        UmbClientMgr.openModalWindow(resUrl, picker.title ? picker.title : "Choose an " + picker.TreeAlias + " node:", true, picker.width, picker.height, 0, 0, false, function (mdlwnd) {
            picker.data = mdlwnd.outVal;
            if (picker.data) return onresult(picker);
            UmbClientMgr.mainWindow().UmbSpeechBubble.ShowMessage('warning', 'Result have to be chosen', 'Can\'t continue, no one node been selected!');
        });
    }

    function uuidFast() {
        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''), uuid = new Array(36), rnd = 0, r;
        for (var i = 0; i < 36; i++) {
            if (i == 8 || i == 13 || i == 18 || i == 23) {
                uuid[i] = '-';
            } else if (i == 14) {
                uuid[i] = '4';
            } else {
                if (rnd <= 0x02) rnd = 0x2000000 + (Math.random() * 0x1000000) | 0;
                r = rnd & 0xf;
                rnd = rnd >> 4;
                uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
            }
        }
        var s = uuid.join('').replace(/-/g, "");
        return s;
    }
    function TransformTemplate(template, el, asObject) {
        var obj = this;
        var res = String(template);
        for (var pname in el) {
            res = res.replace(new RegExp("##" + pname + "##", "g"), el[pname]);
        }
        res = res.replace(new RegExp("##[^##]*##", "g"), ""); //replace rest to empty string
        return asObject ? { 'result': res, 'template': template, 'data': el} : res;
    }
    defaultPicker = {
        width: 400,
        height: 500,
        url: '/umbraco/dialogs/treepickerex.aspx?treeType=##TreeAlias##&contextMenu=true&isDialog=false&app=##TreeAlias##&nodeKey=##StartFrom##&selected=##path##',
        editurl: '/umbraco/editContent.aspx?id=##data##',
        editwidth: 800,
        editheight: 600
    };
})(jQuery);
